package com.iwdnb.gkgz.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.iwdnb.bmnf.common.eventbus.EventBus;
import com.iwdnb.bmnf.common.excel.core.ExcelService;
import com.iwdnb.bmnf.common.excel.model.ExcelDefinition;
import com.iwdnb.bmnf.common.excel.model.ExcelField;
import com.iwdnb.bmnf.common.model.result.Result;
import com.iwdnb.gkgz.application.event.StockBackValidateEventHandler;
import com.iwdnb.gkgz.application.model.request.AddStrategyTradeStockDataRequest;
import com.iwdnb.gkgz.application.model.vo.StrategyTradeScore;
import com.iwdnb.gkgz.application.model.vo.StrategyTradeScoreInfo;
import com.iwdnb.gkgz.application.model.vo.StrategyTradeStatisticData;
import com.iwdnb.gkgz.application.service.StockService;
import com.iwdnb.gkgz.application.service.StrategyTradeService;
import com.iwdnb.gkgz.application.strategy.StockBackValidateService;
import com.iwdnb.gkgz.common.model.dto.Stock;
import com.iwdnb.gkgz.common.model.dto.StockDayData;
import com.iwdnb.gkgz.common.model.dto.StrategyImageStatisticDTO;
import com.iwdnb.gkgz.common.model.dto.StrategyTradeDTO;
import com.iwdnb.gkgz.common.utils.StockBlackListUtils;
import com.iwdnb.gkgz.infrastructure.dao.repo.StockDayDataRepository;
import com.iwdnb.wwzy.dao.MetaDataDAO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static com.iwdnb.gkgz.common.constant.GkgzConstants.OBJECT_CODE_STRATEGY_TRADE;

/**
 * 策略交易
 */
@RestController
@RequestMapping("/api/stock/strategy")
public class StockStrategyController {

    @Autowired
    private StrategyTradeService strategyTradeService;
    @Autowired
    private StockBackValidateService stockBackValidateService;
    @Autowired
    private StockDayDataRepository stockDayDataRepository;

    @Autowired
    private StockService stockService;
    @Autowired
    private ExcelService excelService;

    @Autowired
    private MetaDataDAO metaDataDAO;
    @Autowired
    private Executor executor;
    private static final int pageSize = 1000;

    /**
     * 添加股票交易策略买点数据
     *
     * @param request
     * @return
     */
    @PostMapping(value = "/addAllStrategyTradeStockData")
    public Result<Void> addAllStrategyTradeStockData(@RequestBody AddStrategyTradeStockDataRequest request) {
        List<Stock> stockList = stockService.queryStockList();
        List<String> codes = stockList.stream()
            .map(stock -> stock.getCode()).collect(Collectors.toList());
        codes = StockBlackListUtils.getCanBuyCodeList(codes);
        int end = request.getEnd() > codes.size() ? codes.size() : request.getEnd();
        codes = codes.subList(request.getBegin(), end);
        request.setCodes(StringUtils.join(codes, ","));
        strategyTradeService.addStrategyTradeStockData(request);
        return Result.getSuccessResult(null);
    }

    /**
     * 添加股票交易策略买点数据
     *
     * @param request
     * @return
     */
    @PostMapping(value = "/addStrategyTradeStockData")
    public Result<Void> addStrategyTradeStockData(@RequestBody AddStrategyTradeStockDataRequest request) {
        strategyTradeService.addStrategyTradeStockData(request);
        return Result.getSuccessResult(null);
    }

    /**
     * 回测股票交易策略数据
     *
     * @return
     */
    @GetMapping(value = "/doBackStrategyTrade")
    public Result<Void> doBackStrategyTrade(String uuid, String codes) {
        List<String> codeList = Lists.newArrayList(codes.split(","));
        for (String code : codeList) {
            executor.execute(() -> {
                strategyTradeService.doBackStrategyTrade(uuid, code);
            });
        }
        return Result.getSuccessResult(null);
    }

    /**
     * 删除股票交易策略数据
     *
     * @return
     */
    @GetMapping(value = "/deleteStrategyTrades")
    public Result<Void> deleteStrategyTrades(String uuid, String codes) {
        List<String> codeList = Lists.newArrayList(codes.split(","));
        strategyTradeService.deleteStrategyTrades(uuid, codeList);
        return Result.getSuccessResult(null);
    }

    /**
     * 添加股票交易策略买点数据
     *
     * @param request
     * @return
     */
    @PostMapping(value = "/doAllBackValidate")
    public Result<Void> doAllBackValidate(@RequestBody AddStrategyTradeStockDataRequest request) {
        EventBus.sendEvent(StockBackValidateEventHandler.EVENT_TOPIC, request);
        return Result.getSuccessResult(null);
    }

    /**
     * 获取股票策略交易买入日期
     *
     * @return
     */
    @GetMapping(value = "/queryBackValidateDateList")
    public Result<List<StrategyTradeDTO>> queryBackValidateDateList(String code, String strategy) {
        List<StockDayData> stockDayDataList = stockDayDataRepository.queryAll(code);
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return Result.getErrorResult("股票日K数据为空");
        }
        return Result.getSuccessResult(
            stockBackValidateService.queryBackValidateDateList(code, strategy, stockDayDataList,
                new AddStrategyTradeStockDataRequest()));
    }

    /**
     * 屠龙刀交易信息统计
     *
     * @return
     */
    @GetMapping(value = "/statisticTradeList")
    public Result statisticTradeList(String groups, String loadDataFlag) throws IOException {
        List<String> groupList = Lists.newArrayList(groups.split(","));
        List<StrategyTradeStatisticData> list = strategyTradeService.statisticTradeList(groupList, loadDataFlag);
        ExcelDefinition excelDefinition = excelService.getExcelDefinition("StrategyTradeStatisticData", null);
        List<ExcelField> fields = excelDefinition.getFields();
        List<String> groupNames = new ArrayList<>();
        for (int i = 1; i <= groupList.size(); i++) {
            groupNames.add("group" + i);
        }
        fields = fields.stream().filter(
            field -> !field.getName().startsWith("group") || groupNames.contains(field.getName())).collect(
            Collectors.toList());

        for (ExcelField field : fields) {
            if (field.getName().startsWith("group")) {
                int index = Integer.parseInt(field.getName().replace("group", ""));
                field.setTitle(groupList.get(index - 1));
            }
        }
        excelDefinition.setFields(fields);
        File file = new File(
            "/Users/wubinchuan/Documents/temp/statisticTradeList_" + groups + "_" + DateUtil.format(new Date(),
                DatePattern.PURE_DATETIME_PATTERN) + ".xlsx");
        excelService.exportExcel(excelDefinition, list, new FileOutputStream(file), null);
        return Result.getSuccessResult("");
    }

    /**
     * 屠龙刀初始化策略交易评分
     *
     * @return
     */
    @GetMapping(value = "/initTradeScore")
    public Result<List<StrategyTradeScore>> initTradeScore(String groups) throws IOException {
        List<String> groupList = Lists.newArrayList(groups.split(","));
        List<StrategyTradeScore> list = strategyTradeService.initTradeScore(groupList);
        return Result.getSuccessResult(list);
    }

    /**
     * 屠龙刀计算股票得分
     *
     * @return
     */
    @GetMapping(value = "/calculateTradeScore")
    public Result<StrategyTradeScoreInfo> calculateTradeScore(Long strategyTradeId) {
        StrategyTradeDTO strategyTradeDTO = metaDataDAO.get(OBJECT_CODE_STRATEGY_TRADE, strategyTradeId,
            StrategyTradeDTO.class);
        StrategyTradeScoreInfo strategyTradeScoreInfo = strategyTradeService.calculateTradeScore(strategyTradeDTO,null);
        return Result.getSuccessResult(strategyTradeScoreInfo);
    }


    /**
     * 屠龙刀计算股票得分
     *
     * @return
     */
    @GetMapping(value = "/calculateAllTradeScore")
    public Result<String> calculateAllTradeScore()  {
        strategyTradeService.calculateAllTradeScore();
        return Result.getSuccessResult(null);
    }

    /**
     * 股票策略交易实际计算
     *
     * @return
     */
    @GetMapping(value = "/doCaculateBackValidate")
    public Result<List<String>> doCaculateBackValidate(String strategy, int buyBatchNum, String multipleFlag) {
        stockBackValidateService.doCaculateBackValidate(strategy, buyBatchNum, multipleFlag);
        return Result.getSuccessResult(null);
    }

    /**
     * 股票策略结果按走势形态统计
     *
     * @return
     */
    @GetMapping(value = "/doStockImageStatistic")
    public Result<List<StrategyImageStatisticDTO>> doStockImageStatistic(String strategy, String profitType) {
        List<StrategyImageStatisticDTO> strategyImageStatisticDTOList = strategyTradeService.doStockImageStatistic(
            strategy, profitType);
        return Result.getSuccessResult(strategyImageStatisticDTOList);
    }
}
